#include "app/InputEvent.h"
#include "gui/GUIApplication.h"
#include "gui/objects/GUIRoute.h"
#include "gui/layers/CarLayer.h"
#include "gui/layers/MapLayer.h"
#include "gui/layers/InfoLayer.h"
#include "gui/layers/RouteLayer.h"
#include "util/logger/LoggerManager.h"
#include <sstream>

namespace gui {

GUIApplication::GUIApplication(Map* map, RouteController* routeController, CarController* carController,
		int viewportX, int viewportY, int screenW, int screenH,
		int screenBPP, std::string screenCaption, bool fullscreen) {

	stringstream texto;	texto.str("");
	texto << "Creando GUIApplication con valores:"
		<< "\n\t  viewportX:viewportY [metros] = " << viewportX << ":" << viewportY
		<< "\n\t  screenWidth[px],screenHeight[px] = " << screenW << "," << screenH
		<< "\n\t  screenBPP = " << screenBPP
		<< "\n\t  screenCaption = " << screenCaption
		<< "\n\t  fullscreen? = " << fullscreen;
	this->logger()->info(texto.str());

	// se crea el motor de graficos
	this->engine = new GUIEngine(screenW,screenH,screenBPP,screenCaption,fullscreen);

	// Se necesita transformar estos valores a "pixel standard"
	viewportX = gui::toPixels(viewportX);
	viewportY = gui::toPixels(viewportY);
	texto.str("");
	texto << "Convirtiendo valores del viewport a std pixel..." << "\n\t  viewportX [px std] = "
		<< viewportX << "\n\t  viewportY [px std] = " << viewportY;
	this->logger()->info(texto.str());

	// Calculo la escala deseada
	double xScale = (double) screenW / viewportX;
	double yScale = (double) screenH / viewportY;

	texto.str("");
	texto << "GUIEngine utilizara las siguientes escalas..." << "\n\t  xScale = " << xScale << "\n\t  yScale = " << yScale;
	this->logger()->info(texto.str());

	// Prueba inicializar el engine
	if (!this->engine->start(app::ApplicationConfig::getBooleanProperty("showSplashScreen"))) {
		logger()->error("No se pudo inicializar el motor grafico.");
		return;
	}

	SurfaceFactory* surfaceFactory = this->engine->getSurfaceFactory();

	this->mapLayer = new MapLayer(surfaceFactory, map);
	this->routeLayer = new RouteLayer(surfaceFactory, routeController);
	this->carLayer = new CarLayer(surfaceFactory, carController);
	this->infoLayer = new InfoLayer(surfaceFactory, carController, routeController, screenH);

	// se crea el viewport, porcion visible mapa
	// pasandole como parametros de ancho y alto el tamanio de la porcion de mapa que se dibujara en el, en pixeles standard
	this->viewport = new Viewport(carController, this->mapLayer, this->infoLayer, screenW, screenH, xScale, yScale);
	this->viewport->addMiddleLayer(this->carLayer);
	this->viewport->addMiddleLayer(this->routeLayer);
}

GUIApplication::~GUIApplication() {
	this->engine->stop();
	delete this->engine;
	delete this->viewport;
	delete this->mapLayer;
	delete this->carLayer;
	delete this->routeLayer;
	delete this->infoLayer;
}

util::Logger* GUIApplication::logger() {
	return util::LoggerManager::getInstance()->getLogger();
}

bool GUIApplication::pollEvent(InputEvent* event) {
	return this->engine->pollEvent(event);
}

void GUIApplication::refreshScreen() {
	//Se pasa al engine la superficie unica a graficar
	this->engine->clearScreen();
	Surface* plainSurface = this->viewport->getPlainSurface();
	this->engine->drawSurface(plainSurface);
	delete plainSurface;

}

}

